if (heapSize < 200000) then
        heapSize = 2000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"

fname = getOpenFileName \
caption:"Open .scn from Mesh folder" \
types:"Natural Doctrine  (*.scn)|*.scn" \
historyCategory:"NaturalDoctrineObjectPresets"
f = fopen fname "rb"

clearlistener()
fn readHalfFloat fstream = (
    hf=readshort fstream #unsigned
    sign = bit.get hf 16
    exponent = (bit.shift (bit.and hf (bit.hexasint "7C00")) -10) as integer - 16
    fraction = bit.and hf (bit.hexasint "03FF")
    if sign==true then sign = 1 else sign = 0
    exponentF = exponent + 127
    outputAsFloat = bit.or (bit.or (bit.shift fraction 13) \
    (bit.shift exponentF 23)) (bit.shift sign 31)
    return bit.intasfloat outputasfloat*2
    )
fn readFixedString bstream fixedLen = (
local str = ""
for i = 1 to fixedLen do (
str += bit.intAsChar (ReadByte bstream #unsigned))
str
)
struct weight_data
(
	boneids,weights
)
clearlistener()

fseek f 0x0 #seek_set
SCN=readFixedString f 4
MathPathCount = Readlong f
MathCount = Readlong f
MathOff = Readlong f
MCount = Readlong f
MathSecSize = Readlong f
BoneCount = Readlong f
BoneOff = Readlong f
MeshCount = Readlong f
MeshOff = Readlong f

BNArr = #()
MeshName = #()
HT = dotNetObject "System.Collections.Hashtable"
BoneParent = #()
BoneTable = #()
BoneNames = #()

fseek f BoneOff #seek_set

for a = 1 to (BoneCount-MeshCount) do (

c11 = ReadFloat f; c12 = ReadFloat f; c13 = ReadFloat f; c14 = ReadFloat f	
c21 = ReadFloat f; c22 = ReadFloat f; c23 = ReadFloat f; c24 = ReadFloat f	
c31 = ReadFloat f; c32 = ReadFloat f; c33 = ReadFloat f; c34 = ReadFloat f
c41 = ReadFloat f; c42 = ReadFloat f; c43 = ReadFloat f; c44 = ReadFloat f

			
BoneName=readFixedString f 32
	
fseek f 0x160 #seek_cur
	
Unk1 = Readlong f	
BoneHashId = (Readlong f #unsigned) as string	
BoneId = Readlong f	
BoneParent = Readlong f #unsigned		
LongCount = Readlong f
Unk2 = Readlong f		
for x = 1 to LongCount do (
BoneChild = Readlong f  
)	

HT.Add (BoneHashId) BoneName 

tfm = matrix3 [c11,c12,c13] [c21,c22,c23] [c31,c32,c33] ([c41,c42,c43]*100)
	
newBone = bonesys.createbone	\
				  tfm.row4	\
				  (tfm.row4 + 0.01 * (normalize tfm.row1)) \
				  (normalize tfm.row3)
			newBone.name = BoneName
			newBone.width  = 0.01
			newBone.height = 0.01
			newBone.transform = tfm
			newBone.setBoneEnable false 0
			newBone.wirecolor = white
			newbone.showlinks = true
			newBone.pos.controller      = TCB_position ()
			newBone.rotation.controller = TCB_rotation ()				  
append BNArr newBone					 
)

for a = 1 to MeshCount do (

fseek f 0x40 #seek_cur
			
append MeshName (readFixedString f 32)

fseek f 0x160 #seek_cur
	
Unk1 = Readlong f	
Unk2 = Readlong f #unsigned	
Unk3 = Readlong f	
Unk4 = Readlong f	
CountLong = Readlong f	
	
for x = 1 to CountLong do (
Long = Readlong f  
)	
Unk5 = Readlong f #unsigned				  
)

Print ("Bone End @ 0x"+((bit.intAsHex(ftell f))as string))

fseek f MeshOff #seek_set

Print ("Mesh Off @ 0x"+((bit.intAsHex(ftell f))as string))

for i = 1 to MeshCount do (	
	
VertexCount = Readlong f
FaceCount = Readlong f
VertexId = Readlong f
UCount = Readlong f
Unk1 = ReadFloat f
UsedBoneCount = Readlong f
Unk2 = ReadFloat f

fseek f 0x60 #seek_cur

vertArray = #()
Facearray = #()	
UV_array = #()
Weight_array =#()
BoneMap =#()	

Print ("Vertex Start @ 0x"+((bit.intAsHex(ftell f))as string))
	
for x = 1 to VertexCount do (
	
getPos = ftell f + 44		

vx = Readfloat f
vy = Readfloat f
vz = Readfloat f
	
fseek f 0xC #seek_cur	

tu=readHalfFloat f	
tv=readHalfFloat f*-1	
	
fseek f 0x8 #seek_cur		
	
weight1 = readbyte f #unsigned	
weight2 = readbyte f #unsigned	
weight3 = readbyte f #unsigned	
weight4 = readbyte f #unsigned	
	
bone1 = readbyte f #unsigned	
bone2 = readbyte f #unsigned	
bone3 = readbyte f #unsigned	
bone4 = readbyte f #unsigned
	
w = (weight_data boneids:#() weights:#())
maxweight = 0
if(weight1 != 0) then
   maxweight = maxweight + weight1
if(weight2 != 0) then
   maxweight = maxweight + weight2
if(weight3 != 0) then
   maxweight = maxweight + weight3
if(weight4 != 0) then
   maxweight = maxweight + weight4


if(maxweight != 0) then (
      if(weight1 != 0) then (
         w1 = weight1 as float
         append w.boneids (bone1 + 1)
         append w.weights (w1/255.0)
      )
      if(weight2 != 0) then (
         w2 = weight2 as float
         append w.boneids (bone2 + 1)
         append w.weights (w2/255.0)
      )
      if(weight3 != 0) then (
         w3 = weight3 as float
         append w.boneids (bone3 + 1)
         append w.weights (w3/255.0)
      )
      if(weight4 != 0) then (
         w4 = weight4 as float
         append w.boneids (bone4 + 1)
        append w.weights (w4/255.0)
      )      
   )
fseek f getPos #seek_set 
append Weight_array w			   
append vertArray [vx,vy,vz]
append UV_array [tu,tv,0]	 
)	

Print ("Vertex End @ 0x"+((bit.intAsHex(ftell f))as string))

for x = 1 to FaceCount/3 do (
f1 = (Readlong f #unsigned + 1)
f2 = (Readlong f #unsigned + 1) 
f3 = (Readlong f #unsigned + 1) 
append Facearray [f1,f2,f3]
)

Print ("Face End @ 0x"+((bit.intAsHex(ftell f))as string))
	
for i = 1 to UsedBoneCount do (
bonehash = (readlong f #unsigned) as string	
append BoneMap bonehash 	
)

for a = 1 to UsedBoneCount do (	
getPos = ftell f + 64			
fseek f getPos #seek_set	
)	

Print ("Section End @ 0x"+((bit.intAsHex(ftell f))as string))

msh = mesh vertices:vertArray faces:faceArray
msh.name=MeshName[i]
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count do setTVert msh j UV_array[j]
for j = 1 to faceArray.count do setTVFace msh j faceArray[j]
msh.displayByLayer = false
msh.backfacecull = true
msh.wirecolor = (color 230 200 210)

max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod

for i = 1 to UsedBoneCount do
(
	maxbone = getnodebyname HT.item[BoneMap[i]]
	if i != UsedBoneCount then 
		skinOps.addBone skinMod maxbone 0
	else
		skinOps.addBone skinMod maxbone 1
)
modPanel.setCurrentObject skinMod
for i = 1 to VertexCount do (
   w = Weight_array[i]
   bi = #() --bone index array
   wv = #() --weight value array
   
   for j = 1 to w.boneids.count do
   (
      boneid = w.boneids[j]
      weight = w.weights[j]
      append bi boneid
      append wv weight
   )   
   
   skinOps.ReplaceVertexWeights skinMod i bi wv
   
)
)

fclose f